package huyaoying.study.nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;

/**
 * Java NIO分散/聚集或向量I/O ：
 *      Java NIO可以读取一组缓冲区或则写入一组缓冲区
 * 原文链接：https://www.yiibai.com/java_nio/scatter-gather-or-vectored-input-output.html#article-start
 *
 * @author huyaoying
 * @date 2022/2/8
 */
public class ScatterGatherIO {

    /**
     * 第一个缓冲区在控制台上打印随机输出，第二个缓冲区在控制台上打印“Java NIO”。
     *
     * @param args arg游戏
     */
    public static void main(String[] args) {
        String data = "Java NIO";
        // 两个缓冲存入数据
        gatherBytes(data);
        // 将数据读入两个缓冲区
        scatterBytes();
    }


    /**
     * 将一组缓冲区写入文件中
     *
     * @param data 数据
     */
    public static void gatherBytes(String data) {
        String relativelyPath = System.getProperty("user.dir");

        // 缓存区 buffer1 只有8个字节 放入了一个整数     buffer2 有400字节且放入了传入的参数
        ByteBuffer buffer1 = ByteBuffer.allocate(8);
        ByteBuffer buffer2 = ByteBuffer.allocate(400);
        buffer1.asIntBuffer().put(420);
        buffer2.asCharBuffer().put(data);

        // 创建通道
        GatheringByteChannel gatherer = createChannelInstance(relativelyPath+"/src/main/resources/testout.txt", true);

        // 写入内容到文件
        try {
            gatherer.write(new ByteBuffer[] { buffer1, buffer2 });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 从文件中读取内容到一组缓冲区中
     */
    public static void scatterBytes() {
        String relativelyPath = System.getProperty("user.dir");

        ByteBuffer buffer1 = ByteBuffer.allocate(8);
        ByteBuffer buffer2 = ByteBuffer.allocate(400);
        ScatteringByteChannel scatter = createChannelInstance(relativelyPath+"/src/main/resources/testout.txt", false);

        try {
            scatter.read(new ByteBuffer[] { buffer1, buffer2 });
        } catch (Exception e) {
            e.printStackTrace();
        }

        // rewind()方法主要思路就是重置属性，把一些变化或可能会变化属性(position\limit\capacity)重置成初始模样。
        buffer1.rewind();
        buffer2.rewind();

        int bufferOne = buffer1.asIntBuffer().get();
        String bufferTwo = buffer2.asCharBuffer().toString();

        System.out.println(bufferOne);
        System.out.println(bufferTwo);
    }

    /**
     * 创建通道实例
     *
     * @param file     文件
     * @param isOutput 输出
     * @return {@link FileChannel}
     */
    public static FileChannel createChannelInstance(String file, boolean isOutput) {
        FileChannel FChannel = null;
        try {
            if (isOutput) {
                FChannel = new FileOutputStream(file).getChannel();
            } else {
                FChannel = new FileInputStream(file).getChannel();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return FChannel;
    }


}
